﻿using System.Collections;
using System.Runtime.Intrinsics.Arm;
using System.Text;
using CppAst;
using Microsoft.VisualBasic;

namespace ast;

public enum BuildTarget
{
    Go = 0,
    Ts = 1,
}

public class ExportConfig
{
    public ModuleInfo ModuleInfo;

    public string outDir;

    public BuildTarget Target;

    public ExportConfig(ModuleInfo moduleInfo, string outDir, BuildTarget target)
    {
        this.ModuleInfo = moduleInfo;
        this.outDir = outDir;
        this.Target = target;
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["const char*", "", "int", ""], "gostring"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["char const char*", "", "int", ""], "gostring"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["char*", "", "int", ""], "gostring"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["b3Vector3", ""], "[3]float32"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["const b3Vector3 &", ""], "[3]float32"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["const b3Vector3", ""], "[3]float32"));
        // this.ParameterTypeToTypeMap.Add(new ParametersInfo(["b3Vector3 const &", ""], "[3]float32"));
    }
    // go call cppwrap
    // cppwrap call c

    public void Run()
    {
        Directory.CreateDirectory(outDir);
        ProcessFunctions(ReplaceParaName);
        ProcessFunctions(BuildFunctionParameters);
        ProcessClasses((info, builders) =>
        {
            // PrintGoInterface(info, builders);
            if (this.Target == BuildTarget.Go)
            {
                PrintGoImpl(info, builders);
            }
            else
            {
                PrintTsImpl(info, builders);
            }

            PrintClassCppWrapBody(info, builders);
        });
        if (this.Target == BuildTarget.Go)
        {
            ProcessGlobalFunctions(GenerateGlobalFunctionInGo);
        }

        if (this.Target == BuildTarget.Ts)
        {
            ProcessGlobalFunctions(GenerateGlobalFunctionInTs);
        }

        ProcessGlobalFunctions(GenerateGlobalFunctionInCpp);
        if (this.Target == BuildTarget.Go)
        {
            ProcessEnum(PrintGoEnum);
        }

        if (this.Target == BuildTarget.Ts)
        {
            ProcessEnum(PrintTsEnum);
        }

        ProcessFiles(WriteFile);
    }

    private void GenerateGlobalFunctionInTs(FunctionInfo arg1, int arg2, Builders arg3)
    {
        // throw new NotImplementedException();
    }


    private void ProcessEnum(Action<EnumInfo> func)
    {
        foreach (var (key, enumInfo) in ModuleInfo.GlobalEnum)
        {
            func(enumInfo);
        }
    }

    private void PrintGoEnum(EnumInfo enumInfo)
    {
        var enumName = GoTypeUtil.GetGoEnumName(enumInfo.CppEnum);
        var prefix = GetPrefix(enumInfo.CppEnum.Comment, "");
        enumInfo.FileInfo.Builders.goBuilder.Append(prefix);

        enumInfo.FileInfo.Builders.goBuilder.Append(
            $"type {enumName} {GoTypeUtil.GetGoTypeString(enumInfo.CppEnum.IntegerType)}\n\n");
        enumInfo.FileInfo.Builders.goBuilder.Append($"const (\n");
        foreach (var cppEnumItem in enumInfo.CppEnum.Items)
        {
            var valuePrefix = GetPrefix(cppEnumItem.Comment, "");
            enumInfo.FileInfo.Builders.goBuilder.Append(valuePrefix);


            enumInfo.FileInfo.Builders.goBuilder.Append(
                $"\t{enumName}_{cppEnumItem.Name} {enumName} ={getEnumValue(enumInfo.CppEnum.IntegerType, cppEnumItem.Value)}\n");
        }

        enumInfo.FileInfo.Builders.goBuilder.Append($")\n");
    }

    private void PrintTsEnum(EnumInfo enumInfo)
    {
        var enumName = TsTypeUtil.GetTsEnumName(enumInfo.CppEnum);
        var prefix = GetPrefix(enumInfo.CppEnum.Comment, "");
        enumInfo.FileInfo.Builders.tsBuilder.Append(prefix);

        enumInfo.FileInfo.Builders.tsBuilder.Append(
            $"declare enum {enumName} {{\n");
        foreach (var cppEnumItem in enumInfo.CppEnum.Items)
        {
            var valuePrefix = GetPrefix(cppEnumItem.Comment, "");
            enumInfo.FileInfo.Builders.tsBuilder.Append(valuePrefix);


            enumInfo.FileInfo.Builders.tsBuilder.Append(
                $"\t{cppEnumItem.Name}  ={getEnumValue(enumInfo.CppEnum.IntegerType, cppEnumItem.Value)},\n");
        }

        enumInfo.FileInfo.Builders.tsBuilder.Append($"}}\n");
    }


    private long getEnumValue(CppType cppType, long value)
    {
        if (cppType is not CppPrimitiveType kind)
        {
            return value;
        }

        switch (kind.Kind)
        {
            case CppPrimitiveKind.WChar:
                return (short)(value);
            case CppPrimitiveKind.Char:
                return (sbyte)(value);
            case CppPrimitiveKind.UnsignedChar:
                return (byte)(value);
            case CppPrimitiveKind.SignedChar:
                return (sbyte)(value);
            case CppPrimitiveKind.Short:
                return (short)(value);
            case CppPrimitiveKind.Int:
                return (int)(value);
            case CppPrimitiveKind.Long:
                return (long)(value);
            case CppPrimitiveKind.LongLong:
                return (long)(value);

            case CppPrimitiveKind.UnsignedShort:
                return (ushort)(value);
            case CppPrimitiveKind.UnsignedInt:
                return (uint)(value);
            case CppPrimitiveKind.UnsignedLongLong:
                return (long)(ulong)(value);
        }

        return value;
    }

    private void ReplaceParaName(FunctionInfo functionInfo, Builders arg2)
    {
        for (var index = 0; index < functionInfo.Function.Parameters.Count; index++)
        {
            var functionParameter = functionInfo.Function.Parameters[index];
            functionParameter.Name = validParaName(functionParameter.Name, index);
        }
    }

    private string GetPlatFormFlagString()
    {
        if (OperatingSystem.IsWindows())
        {
            return "windows";
        }

        if (OperatingSystem.IsLinux())
        {
            return "linux";
        }

        if (OperatingSystem.IsMacOS())
        {
            return "darwin";
        }

        throw new Exception("not supported");
    }

    private string GetPlatFormShortString()
    {
        if (OperatingSystem.IsWindows())
        {
            return "w";
        }

        if (OperatingSystem.IsLinux())
        {
            return "l";
        }

        if (OperatingSystem.IsMacOS())
        {
            return "d";
        }

        throw new Exception("not supported");
    }

    private string GetPlatFormMacroString()
    {
        if (OperatingSystem.IsWindows())
        {
            return "__WIN32__";
        }

        if (OperatingSystem.IsLinux())
        {
            return "__linux__";
        }

        if (OperatingSystem.IsMacOS())
        {
            return "__APPLE__";
        }

        throw new Exception("not supported");
    }

    private void WriteFile(FileInfo fileInfo)
    {
        var builders = fileInfo.Builders;
        var goContent = builders.goBuilder.ToString();
        var cgoContent = builders.cgoBuilder.ToString();
        var cppIncludeContentBuilder = new StringBuilder();
        if (ModuleInfo.platformOnly)
        {
            cppIncludeContentBuilder.Append($"#if defined {GetPlatFormMacroString()}\n");
        }

        var finalImport = new SortedSet<string>();
        foreach (var se in fileInfo.SortedImport)
        {
            if (se == null || string.IsNullOrEmpty(se))
            {
                continue;
            }

            var extraInclude = this.ModuleInfo.GetIncludePath(se);
            var ok = ModuleInfo.extraFileInclude.TryGetValue(extraInclude, out var refInclude);
            if (ok)
            {
                refInclude.ForEach(a => finalImport.Add(a));
            }

            finalImport.Add(extraInclude);
        }

        foreach (var se in finalImport)
        {
            var extraInclude = this.ModuleInfo.GetIncludePath(se);
            cppIncludeContentBuilder.Append($"#include \"{extraInclude}\"\n");
        }

        cppIncludeContentBuilder.Append("#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
        builders.cppBuilder.Append("#ifdef __cplusplus\n}\n#endif\n");
        var directoryName = Path.GetDirectoryName(fileInfo.SourcePath);
        var name = Path.GetFileName(fileInfo.SourcePath);
        name = name.Replace(".", "_");
        if (ModuleInfo.platformOnly)
        {
            name = name + $"_{GetPlatFormShortString()}";
        }

        var dir = Path.GetRelativePath(ModuleInfo.ModuleDir, directoryName);
        dir = dir.Replace(".", "");
        dir = dir.Replace("\\", "_");
        dir = dir.Replace("/", "_");
        goContent = $"package {ModuleInfo.ModuleName}\n\n" +
                    $"/*\n" +
                    $"#include<stdint.h>\n" +
                    $"#include<stdbool.h>\n" +
                    $"{cgoContent}\n" +
                    $"*/\n" +
                    $"import \"C\"\n" +
                    $"import \"unsafe\"\n" +
                    $"import \"gitee.com/hasika/cgo\"\n\n" +
                    $"var _ unsafe.Pointer\n" +
                    $"var _ cgo.NotUsed\n\n" +
                    $"{goContent}";
        if (ModuleInfo.platformOnly)
        {
            goContent = $"//go:build {GetPlatFormFlagString()}\n" + goContent;
        }

        var goPath = outDir + "/" + dir + "_" + name + ".go";
        var tsPath = outDir + "/" + dir + "_" + name + ".d.ts";
        var cppPath = outDir + "/" + dir + "_" + name + ".cxx";
        if (string.IsNullOrEmpty(dir))
        {
            goPath = outDir + "/" + name + ".go";
            cppPath = outDir + "/" + name + ".cxx";
        }

        if (ModuleInfo.platformOnly)
        {
            builders.cppBuilder.Append("#endif\n");
        }

        File.WriteAllText(goPath, goContent);
        if (this.Target == BuildTarget.Ts)
        {
            File.WriteAllText(tsPath, builders.tsBuilder.ToString());
        }
        else
        {
            File.WriteAllText(cppPath, cppIncludeContentBuilder.ToString() + builders.cppBuilder.ToString());
        }
    }


    private void GenerateGlobalFunctionInCpp(FunctionInfo functionInfo, int index, Builders builders)
    {
        builders.cppBuilder.AppendFormat("{0}{{\n",
            CWrapperGenerator.GetCppWrapperFunctionSignature(ModuleInfo, ModuleInfo.ModuleName, null,
                functionInfo, index));
        builders.cppBuilder.AppendFormat("{0}", CWrapperGenerator.GetWrapCallRawCppFunctionBody(null, functionInfo));
        builders.cppBuilder.Append("}\n\n");
    }

    private void GenerateGlobalFunctionInGo(FunctionInfo functionInfo, int index, Builders builders)
    {
        builders.cgoBuilder.AppendFormat("extern {0};\n",
            GoWrapperGenerator.GetCgoExternFunctionSignature(ModuleInfo, ModuleInfo.ModuleName, null, functionInfo,
                index));

        var functionSign =
            GoWrapperGenerator.GetGoWrapperFunctionSignature(functionInfo, ModuleInfo, index);
        var prefix = GetPrefix(functionInfo.Function.Comment, functionInfo.Function.ToString());
        builders.goBuilder.Append(prefix);

        builders.goBuilder.AppendFormat("func {0}{{\n", functionSign);
        builders.goBuilder.AppendFormat("{0}",
            GoWrapperGenerator.GetGoWrapperFunctionBody(ModuleInfo, ModuleInfo.ModuleName, null, functionInfo, index));
        builders.goBuilder.Append("}\n");
    }

    public void ProcessClasses(Action<ClassInfo, Builders> classHandler)
    {
        foreach (var fileInfo in ModuleInfo.FileInfos.Values)
        {
            foreach (var classInfo in fileInfo.ClassInfos.Values)
            {
                classHandler(classInfo, fileInfo.Builders);
            }
        }
    }


    public bool IsConstFunction(FunctionInfo functionInfo)
    {
        return functionInfo.Function.IsConst;
    }

    private void PrintTsImpl(ClassInfo classInfo, Builders builders)
    {
        var implName = TsTypeUtil.GetTsClassName(classInfo.ClassType);
        var extendNames = new List<string>();
        foreach (var classTypeBaseType in classInfo.ClassType.BaseTypes)
        {
            var parentType = classTypeBaseType.Type;
            if (parentType is CppClass parentClass)
            {
                var parentClassInfo = ModuleInfo.FindClassInfoOfCppClass(parentClass);
                if (parentClassInfo != null)
                {
                    extendNames.Add(TsTypeUtil.GetTsClassName(parentClassInfo.ClassType));
                }
            }
        }

        if (classInfo.ClassType.Comment != null && !string.IsNullOrEmpty(classInfo.ClassType.Comment.ToString()))
        {
            builders.tsBuilder.Append($"\t/*\n{classInfo.ClassType.Comment.ToString()}\n*/\n");
        }


        builders.tsBuilder.Append($"declare class {implName} ");
        if (extendNames.Count > 0)
        {
            builders.tsBuilder.Append($"extends ");
        }

        foreach (var extendName in extendNames)
        {
            builders.tsBuilder.Append(
                $" {extendName} ");
        }

        builders.tsBuilder.Append($"{{\n");
        var globalFuncBuilder = new StringBuilder();
        foreach (var (name, functionInfoList) in classInfo.FunctionInfos)
        {
            var overrideCnt = functionInfoList.Count;
            for (var funcIndex = 0; funcIndex < overrideCnt; funcIndex++)
            {
                var functionInfo = functionInfoList[funcIndex];
                var cppFunction = functionInfo.Function;
                var comment = "";

                if (!string.IsNullOrEmpty(cppFunction.PropertyName))
                {
                    comment = "//" + cppFunction.PropertyFieldName + "\n";
                }
                else
                {
                    comment = GetPrefix(cppFunction.Comment, cppFunction.ToString());
                }

              
                //检查是否是proper
                if (!string.IsNullOrEmpty(cppFunction.PropertyName))
                {
                    var cleanType = ClassUtil.SimpleType(cppFunction.PropertyType);
                    var supportDirectProp = TsTypeUtil.SupportDirectProp(cleanType);
                    if (supportDirectProp)
                    {
                        continue;
                    }
                    builders.tsBuilder.Append(comment);
                    builders.tsBuilder.Append("\t");
                    //直接作为成员方法直接写入
                    var propFuncSign = TsWrapperGenerator.GenerateMemberTsFunctionSignature(functionInfo, ModuleInfo);
                    builders.tsBuilder.Append(propFuncSign);
                    continue;
                }
                else
                {
                    builders.tsBuilder.Append(comment);
                    builders.tsBuilder.Append("\t");
                    var sign = TsWrapperGenerator.GenerateMemberTsFunctionSignature(functionInfo, ModuleInfo);
                    builders.tsBuilder.Append(sign);
                }

            }
        }

        foreach (var cppField in classInfo.PropertyInfo)
        {
            var comment = "";

            if (!string.IsNullOrEmpty(cppField.Name))
            {
                comment = "//" + cppField.Name + "\n";
            }
            else
            {
                comment = GetPrefix(cppField.Comment, cppField.ToString());
            }
            builders.tsBuilder.Append(comment);
            var cleanType = ClassUtil.SimpleType(cppField.Type);
            var supportDirectProp = TsTypeUtil.SupportDirectProp(cleanType);
            if (supportDirectProp)
            {
                builders.tsBuilder.Append($"{cppField.Name}:{TsTypeUtil.GetTsTypeString(cleanType)};\n");
            }
        }

        builders.tsBuilder.Append("}\n");
        builders.tsBuilder.Append(globalFuncBuilder.ToString());
    }


    public void PrintGoImpl(ClassInfo classInfo, Builders builders)
    {
        var implName = GoTypeUtil.GetGoClassName(classInfo.ClassType);
        var extendNames = new List<string>();
        foreach (var classTypeBaseType in classInfo.ClassType.BaseTypes)
        {
            var parentType = classTypeBaseType.Type;
            if (parentType is CppClass parentClass)
            {
                var parentClassInfo = ModuleInfo.FindClassInfoOfCppClass(parentClass);
                if (parentClassInfo != null)
                {
                    extendNames.Add(GoTypeUtil.GetGoClassName(parentClassInfo.ClassType));
                }
            }
        }

        if (classInfo.ClassType.Comment != null && !string.IsNullOrEmpty(classInfo.ClassType.Comment.ToString()))
        {
            builders.goBuilder.Append($"/*\n{classInfo.ClassType.Comment.ToString()}\n*/\n");
        }


        builders.goBuilder.Append($"type {implName} uintptr\n\n");
        foreach (var extendName in extendNames)
        {
            builders.goBuilder.Append(
                $"func (p {implName}) As{extendName}() {extendName} {{\n\treturn {extendName}(p)\n}}\n");
        }

        foreach (var (name, functionInfoList) in classInfo.FunctionInfos)
        {
            for (var funcIndex = 0; funcIndex < functionInfoList.Count; funcIndex++)
            {
                var functionInfo = functionInfoList[funcIndex];
                // if (functionInfo.Function.Override)
                // {
                //     continue;
                // }
                builders.cgoBuilder.AppendFormat("extern {0};\n",
                    GoWrapperGenerator.GetCgoExternFunctionSignature(ModuleInfo, classInfo.ModuleInfo.ModuleName,
                        classInfo,
                        functionInfo, funcIndex));
                var functionSign =
                    GoWrapperGenerator.GetGoWrapperFunctionSignature(functionInfo, ModuleInfo,
                        funcIndex);

                var prefix = GetPrefix(functionInfo.Function.Comment, functionInfo.Function.ToString());
                builders.goBuilder.Append(prefix);
                var goTypeName = $"(p {implName}) ";
                if (functionInfo.ClassInfo == null)
                {
                    goTypeName = "";
                }

                builders.goBuilder.Append(
                    $"func {goTypeName}{functionSign}{{\n{GoWrapperGenerator.GetGoWrapperFunctionBody(ModuleInfo, classInfo.ModuleInfo.ModuleName, classInfo, functionInfo, funcIndex)}}}\n\n");
            }
        }
    }


    // public void PrintGoInterface(ClassInfo classInfo, Builders builders)
    // {
    //     var implName = GoTypeUtil.GetGoClassName(classInfo.ClassType, true);
    //     var extendNames = new List<string>();
    //     foreach (var classTypeBaseType in classInfo.ClassType.BaseTypes)
    //     {
    //         var parentType = classTypeBaseType.Type;
    //         if (parentType is CppClass parentClass)
    //         {
    //             var parentClassInfo = ModuleInfo.FindClassInfoOfCppClass(parentClass);
    //             if (parentClassInfo != null)
    //             {
    //                 extendNames.Add(GoTypeUtil.GetGoClassName(parentClassInfo.ClassType, true));
    //             }
    //         }
    //     }
    //
    //     builders.goBuilder.Append($"type {implName} interface {{ \n");
    //     foreach (var extendName in extendNames)
    //     {
    //         builders.goBuilder.Append(
    //             $"\t{extendName} \n");
    //     }
    //
    //     if (extendNames.Count == 0)
    //     {
    //         builders.goBuilder.Append($"\tSetCPtr(cptr uintptr)\n");
    //         builders.goBuilder.Append($"\tGetCPtr() uintptr\n");
    //     }
    //
    //     foreach (var (name, functionInfoList) in classInfo.FunctionInfos)
    //     {
    //         for (var funcIndex = 0; funcIndex < functionInfoList.Count; funcIndex++)
    //         {
    //             var functionInfo = functionInfoList[funcIndex];
    //             if (functionInfo.Function.Override)
    //             {
    //                 continue;
    //             }
    //
    //             if (functionInfo.ClassInfo == null)
    //             {
    //                 continue;
    //             }
    //             var functionSign =
    //                 GoWrapperGenerator.GetGoWrapperFunctionSignature(functionInfo, ModuleInfo,
    //                     funcIndex);
    //             builders.goBuilder.Append(
    //                 $"\t{functionSign}\n");
    //         }
    //     }
    //
    //     builders.goBuilder.Append("}\n");
    // }


    public void PrintClassCppWrapBody(ClassInfo classInfo, Builders builders)
    {
        foreach (var (name, functionInfos) in classInfo.FunctionInfos)
            for (var funcIndex = 0; funcIndex < functionInfos.Count; funcIndex++)
            {
                var functionInfo = functionInfos[funcIndex];
                builders.cppBuilder.AppendFormat("{0}{{\n",
                    CWrapperGenerator.GetCppWrapperFunctionSignature(ModuleInfo, classInfo.ModuleInfo.ModuleName,
                        classInfo,
                        functionInfo, funcIndex));
                builders.cppBuilder.AppendFormat("{0}",
                    CWrapperGenerator.GetWrapCallRawCppFunctionBody(classInfo, functionInfo));
                builders.cppBuilder.Append("}\n\n");
            }
    }


    public static bool FunctionReturnVoid(CppType? functionReturnType)
    {
        if (functionReturnType == null) return true;

        if (functionReturnType is CppPrimitiveType cppPrimitiveType &&
            cppPrimitiveType.Kind == CppPrimitiveKind.Void) return true;

        return false;
    }

    // public StringBuilder goBuilder = new StringBuilder();
    // public StringBuilder cgoBuilder = new StringBuilder();
    // public StringBuilder cppBuilder = new StringBuilder();


    public static CppType GetElementType(CppType inType)
    {
        switch (inType)
        {
            case CppTypeWithElementType elementType:
                return GetElementType(elementType.ElementType);
            default:
                return inType;
        }
    }

    public void ProcessFiles(Action<FileInfo> visitFunc)
    {
        foreach (var (funcName, fileInfo) in ModuleInfo.FileInfos)
        {
            visitFunc(fileInfo);
        }
    }

    public void ProcessGlobalFunctions(Action<FunctionInfo, int, Builders> visitFunc)
    {
        foreach (var functionList in ModuleInfo.GlobalFunction.Values)
        {
            var array = functionList.OrderDescending().ToArray();
            for (var index = 0; index < array.Length; index++)
            {
                var functionInfo = array[index];
                visitFunc(functionInfo, index, functionInfo.FileInfo.Builders);
            }
        }
    }

    public void ProcessFunctions(Action<FunctionInfo, Builders> visitFunc)
    {
        foreach (var (fname, fileInfo) in ModuleInfo.FileInfos)
        {
            foreach (var (cname, classInfo) in fileInfo.ClassInfos)
            {
                foreach (var (funcName, funcInfoList) in classInfo.FunctionInfos)
                {
                    foreach (var functionInfo in funcInfoList.OrderDescending())
                    {
                        visitFunc(functionInfo, fileInfo.Builders);
                    }
                }
            }
        }


        foreach (var functionList in ModuleInfo.GlobalFunction.Values)
        {
            foreach (var functionInfo in functionList.OrderDescending())
            {
                visitFunc(functionInfo, functionInfo.FileInfo.Builders);
            }
        }
    }


    public void BuildFunctionParameters(FunctionInfo funcInfo, Builders builders)
    {
        var cppFunction = funcInfo.Function;
        funcInfo.ExportParameters = BuildExportParas(cppFunction.Parameters);
        funcInfo.ExportReturnType = new ExportType(cppFunction.ReturnType);
    }

    public List<ExportPara> BuildExportParas(CppContainerList<CppParameter> parameters)
    {
        var ret = new List<ExportPara>();
        foreach (var cppParameter in parameters)
        {
            ret.Add(new ExportPara(cppParameter));
        }

        return ret;
    }


    public string validParaName(string name, int index)
    {
        if (name == "type")
        {
            return "Type";
        }

        if (name == "map")
        {
            return "Map";
        }

        if (name == "chan")
        {
            return "Chan";
        }

        if (name == "go")
        {
            return "Go";
        }

        if (name == "p")
        {
            return "tmp_arg_p";
        }

        if (name == "C")
        {
            return "tmp_arg_C";
        }

        if (name == "cgo")
        {
            return "tmp_arg_cgo";
        }

        if (name == "unsafe")
        {
            return "tmp_arg_unsafe";
        }

        if (name == ModuleInfo.ModuleName)
        {
            return "tmp_arg_" + ModuleInfo.ModuleName;
        }

        if (string.IsNullOrEmpty(name))
        {
            return "tmp_arg" + index;
        }

        return name;
    }

    public string GetPrefix(CppComment cppComment, string name)
    {
        var comment = "";
        if (cppComment != null)
        {
            comment = cppComment.ToString().Trim();
        }

        if (string.IsNullOrEmpty(comment) && string.IsNullOrEmpty(name))
        {
            return "";
        }

        comment = Strings.Replace(comment, "/*", "");
        comment = Strings.Replace(comment, "*/", "");
        comment = Strings.Replace(comment, "/", "");

        comment = comment + "\n\n" + name;
        comment = comment.Trim();
        return $"/*\n{comment}\n*/\n";
    }
}